# SleepMirror - A reflection of your sleep quality
# 
# sm_humphrey_blue.rb
# This is a specific class to handle an "edge detection" for images that merge or blend
# colors.
# 
# 
# ©2010 JohnGary, LLC.  All Rights Reserved.
# 
# TODO:  5) capture the time it all took.  6)Repeat for 10 times. 7) Write the times and postions out.
# Changelog:
# 
# 
# 

require 'sm_panel'
require "rubygame"

include Rubygame
include Rubygame::Events
include Rubygame::EventActions
include Rubygame::EventTriggers



#The Fixation_circle class defines a Sprite that serves as the fixation circle that the Participant
#is asked to click upon.
class Fixation_circle
  include Sprites::Sprite
  include EventHandler::HasEventHandler
  DEFAULT_ASSET = "Humphrey_blue_fixation_circle_img_sm.png"

  def initialize (px, py)
    super()
    this_dir = File.dirname( __FILE__ )
    file = File.expand_path( DEFAULT_ASSET, this_dir ) # default file
    @image = Surface.load( file )
    @rect = @image.make_rect
    @rect.center=[px,py]
  end
end
#TODO: rDoc this Test_object class
class Test_object
  include Sprites::Sprite
  include EventHandler::HasEventHandler

  attr_accessor :drawn
  def initialize (px, py)
    super()
    @image = Surface.new([20,20])  # A small square.
    #image_color=Rubygame::Color::ColorRGB.new([0.0,0.06,1.0])
    image_color=Rubygame::Color::ColorRGB.new_from_sdl_rgba([0,15,255])
    puts "image_color=#{image_color}"
    #@image.fill(image_color) #I hope this is rgb=[0,15,255]
    #@image.fill(:blue) #I hope this is rgb=[0,15,255]
    @image.fill(image_color) 
    @rect = @image.make_rect
    @rect.center=[px,py]
    @drawn = false #A toggle to indicate I've been drawn, so don't do so again until I'm reset.
  end
end


class SM_humphrey_blue < SM_panel
  attr_accessor :screen, :image
  DEFAULT_ASSET = "Humphrey_blue_bg.jpg"
  DEFAULT_MESSAGE_Y = 50 # This is how far down the screen to put message. They will always be centered.

  # A new SM_humphrey_blue adds a Rubygame::Screen to the base SM_panel class.
  # It is intended to display a yellow background on which we place a "eye sight" circle,
  # then a small square nearby.  The square is a certain shade of blue called Humphrey Blue
  # rgb=[0,15,255].  The Participant is asked to focus on the eye sight circle, click on it
  # and then press the spacebar if they can perceive the small square.  This is repeated
  # a number of times.  We capture the elapsed time for each loop, and the position of the
  # square with respect to the eye sight circle.
  def initialize(name="", instructions="", asset=DEFAULT_ASSET)
    super(name, instructions, asset)
    @answer=[] #override the instance variable to be an array instead of a string
    this_dir = File.dirname( __FILE__ )
    file = File.expand_path( @asset, this_dir ) # default file
    @bg = Surface.load( file ) #@bg is the background image.
    @screen = Screen.new(@bg.size)  
    @bg.blit( @screen, [0,0] ) #paste the bg onto the screen.
    @test_object = Test_object.new(@screen.width/2,@screen.height/2)
    @fixation = Fixation_circle.new(@screen.width/2,@screen.height/2)
    #An array of positions for the fixation circles
    @circles = Array.new( [
                         [@screen.width/2,@screen.height/2],
                         [100,100],
                         [1000,10],
                         [900,700],
                         [30,30],
                         [300,450]
                         ])
     #An array of positions for the blue square to appear
     @squares = Array.new( [
                         [15,15],
                         [1000,750],
                         [10,384],
                         [300,450],
                         [90,90],
                         [900,700]
                          ])

    left_click_hook = EventHook.new(:owner=>self,
       :trigger => MouseReleaseTrigger.new(:mouse_left),
       :action  => MethodAction.new(:splat))
    append_hook(left_click_hook) #Add the left click hooks to the event table

    spacebar_hook = EventHook.new(:owner=>self,
       :trigger => KeyPressTrigger.new(:space),
       :action  => MethodAction.new(:capture_answer))
    append_hook(spacebar_hook) #Add the spacebar hook to the event table

    mouse_moving_hook = EventHook.new(:owner=>self,
       :trigger => MouseMoveTrigger.new,
       :action  => MethodAction.new(:draw_test_object))
    append_hook(mouse_moving_hook) #Add the spacebar hook to the event table
  end
  def say_this (what="What?")
    TTF.setup()
    ttfont_path = File.join(File.dirname(__FILE__),"FreeSans.ttf")
    ttfont = TTF.new( ttfont_path, 20 )
    result = ttfont.render( what,true,:gray)
    result.blit( @screen,[@bg.width/2-result.size[0]/2,DEFAULT_MESSAGE_Y])
  end
  def splat (event)
    #draw the fixation circle at click position if they click inside the circle
    draw_fixation_circle if @fixation.rect.collide_point?(*event.pos)
  end
  def capture_answer(event)
      elapsed_time = Time.new - $t
      @answer << elapsed_time
      puts "Captured >#{event.key}< @ #{elapsed_time.to_s}"
  end
  def exit_script
    puts @answer.to_s
    exit
  end
  #draw_fixation_circle takes a position named pos which should be an [x,y] array
  def draw_fixation_circle
    #TODO: for draw_fixation_circle, implement the dirty_rects approach. See demo_rubygame.rb
    if pos=@circles.pop
      @fixation.undraw(@screen,@bg) #erase the exiting sprite
      @fixation.rect.center=pos
      @fixation.draw(@screen) #draw at the new position
      @test_object.drawn=false #Rest the test object to now drawn
      #Capture the start time t for this set
      $t = Time.now
    else
      @bg.blit(@screen,[0,0]) #Clear the screen by copying the background over it again
      say_this("Test complete.  Press ESC to exit")
    end
    
  end
  def draw_test_object(event)
    et=Time.now-$t
    #puts "et=#{et}"
    if @test_object.drawn
      @test_object.undraw(@screen,@bg) if et > 0.5
    else
      pos=@squares.pop
      @test_object.rect.center=pos
      @test_object.draw(@screen)
      @test_object.drawn=true
    end
  end

  def perform

    say_this("Click on the blue circle to begin. Press Spacebar if you see anything else.")

    # Draw the Fixation circle in its default position
    #@fixation.draw(@screen)
    draw_fixation_circle
    
    # Setup the event queue for this test
    events=EventQueue.new
    events.enable_new_style_events
    # Loop until we get an answer or an exit.

    #Capture the start time t
    #$t = Time.now
    
    loop do
      events = Rubygame::Events.fetch_sdl_events
      events.each do |event|
        handle( event )
      end
      @screen.update
      sleep 0.1
    end
  end

end
